﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <STC89C5xRC.H> //包含STC89C52的头文件
#include <INTRINS.H>

void Delay_1MS(unsigned int count);

void main()
{
	// 让led变为低电位
	P00 = 0;

	// 死循环卡住单片机，让它不要继续往下执行
	while (1) {
		// 对led不断取反，取反就是亮灭转换
		P00 = ~P00;

		// 延时500ms
		Delay_1MS(500);
	}
}

void Delay_1MS(unsigned int count) //@11.0592MHz
{
	unsigned char data i, j;

	while (count > 0) {
		_nop_();
		i = 2;
		j = 199;
		do {
			while (--j)
				;
		} while (--i);

		count--;
	}
}

#include <STC89C5xRC.H>
#include <INTRINS.H>

#define LED_DB P0

// 增加自定义类型，简化代码编写
typedef unsigned char u8;
typedef unsigned int u16;

// 声名延时函数
void Delay_1MS(u16 count);

void main()
{
	// 声名临时变量
	u8 temp = 1;

	// temp是8个bit，对应8个led，1代表亮，正好和P0相反
	// 之后我们只要对temp做左位移，即可实现流水灯
	while (1) {
		// P0 是temp取反;0000 0001 取反 1111 1110
		LED_DB = ~temp;

		// 左移依次为：0000 0001，0000 0010，0000 0100，0000 1000，… 1000 0000
		temp <<= 1;

		// temp是char类型8位，如果等于1000 0000,再左移一位就变成0000 0000，所以如果temp等于0时，需要将temp再设置为1
		if (temp == 0) {
			temp = 1;
		}

		// 延时100ms
		Delay_1MS(100);
	}
}

void Delay_1MS(u16 count) //@11.0592MHz
{
	unsigned char data i, j;

	while (count > 0) {
		count--;
		_nop_();
		i = 2;
		j = 199;
		do {
			while (--j)
				;
		} while (--i);
	}
}

#include "Util.h"

void Delay1ms(u16 count) //@11.0592MHz
{
	u8 i, j;

	while (count > 0)
	{
		count--;
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j)
				;
		} while (--i);
	}
}

#define FOSC 11059200 // 晶振频率
#define NT   12       // 单片机的工作周期为12T

#ifndef __DRI_TIMER0_H__
#define __DRI_TIMER0_H__
#include <STC89C5xRC.H>
#include "Util.h"

typedef void (*Timer0_Callback)(void);

#define MAX_CALLBACK_COUNT 4

/**
 * @brief 定时器初始化
 *
 */
void Dri_Timer0_Init();

/**
 * @brief 提供注册入口，用这个函数注册完成的函数，会以1000Hz的频率被调用
 *
 * @return 成功返回1，失败返回0
 *
 */
bit Dri_Timer0_RegisterCallback(Timer0_Callback);

/**
 * @brief 反注册回调函数，反注册的函数不会再被周期调用
 *
 * @return bit 反注册的结果，成功位1，失败为0
 */
bit Dri_Timer0_DeregisterCallback(Timer0_Callback);
#endif




#include "Dri_Timer0.h"
#include <STDIO.H>

#define T1MS (65536 - FOSC / NT / 1000)

static Timer0_Callback s_timer0_callbacks[MAX_CALLBACK_COUNT];

void Dri_Timer0_Init()
{
	u8 i;
	// 总中断开关
	EA = 1;

	// 定时器中断开关
	ET0 = 1;

	// 设置定时器0的工作模式：16位定时器
	TMOD &= 0xF0;
	TMOD |= 0x01;

	// 设置定时器的初始值
	TL0 = T1MS;
	TH0 = T1MS >> 8;

	// 定时器0的开关
	TR0 = 1;

	for (i = 0; i < MAX_CALLBACK_COUNT; i++)
	{
		s_timer0_callbacks[i] = NULL;
	}
}

bit Dri_Timer0_RegisterCallback(Timer0_Callback callback)
{
	// 判断这个函数有没有被注册过
	u8 i;
	for (i = 0; i < MAX_CALLBACK_COUNT; i++)
	{
		if (s_timer0_callbacks[i] == callback)
		{
			// 如果该函数被注册过，直接返回
			return 1;
		}
	}

	// 注册该函数
	for (i = 0; i < MAX_CALLBACK_COUNT; i++)
	{
		if (s_timer0_callbacks[i] == NULL)
		{
			s_timer0_callbacks[i] = callback;
			return 1;
		}
	}

	return 0;
}

bit Dri_Timer0_DeregisterCallback(Timer0_Callback callback)
{
	u8 i;
	for (i = 0; i < MAX_CALLBACK_COUNT; i++)
	{
		if (s_timer0_callbacks[i] == callback)
		{
			s_timer0_callbacks[i] = NULL;
			return 1;
		}
	}
	return 0;
}

/**
 * @brief 1ms调用一次这个函数
 *
 */
void Dri_Timer0_Func() interrupt 1
{
	u8 i;

	// 定义下次进入时钟中断的时间
	TL0 = T1MS;
	TH0 = T1MS >> 8;

	// 调用所有的回调函数
	for (i = 0; i < MAX_CALLBACK_COUNT; i++)
	{
		if (s_timer0_callbacks[i])
		{
			s_timer0_callbacks[i]();
		}
	}
}







#include <STC89C5xRC.H>
#include "Dri_Timer0.h"

#define LED    P00

static u16 s_counter = 0;

void ToggleLED()
{
	s_counter++;
	// 每500ms切换LED亮灭
	if (s_counter >= 500)
	{
		s_counter = 0;
		LED = ~LED;
	}
}

void main()
{
	Dri_Timer0_Init();
	// 在定时器回中注册回调函数ToogleLED
	// 这样ToogleLED这个函数会每ms被调用一次
	Dri_Timer0_RegisterCallback(ToggleLED);
	while (1)
		;
}